﻿using mozhi.smarterp.Foundation.OperationLogTemplates.Repository;
using Mozhi.Abp.OperationLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Guids;

namespace mozhi.smarterp.Foundation.OperationLogTemplates
{
    public class OperationLogTemplateAppService : FoundationAppService, IOperationLogTemplateAppService
    {
        private IOperationLogTemplateRepository _repository;
        private IGuidGenerator _guidGenerator;

        public OperationLogTemplateAppService(IOperationLogTemplateRepository repository, IGuidGenerator guidGenerator)
        {
            _repository = repository;
            _guidGenerator = guidGenerator;
        }

        public async Task<PagedResultDto<OperationLogTemplateDto>> GetPageListAsync(OperationLogTemplatePageQuery query)
        {
            var templates = await _repository.GetPagedListAsync(query.SkipCount, query.MaxResultCount, query.Sorting, query.Code, true);

            var total = await _repository.GetCountAsync(query.Code);

            var result = new PagedResultDto<OperationLogTemplateDto>();

            result.TotalCount = total;
            result.Items = ObjectMapper.Map<List<OperationLogTemplate>, List<OperationLogTemplateDto>>(templates);

            return result;
        }

        public async Task<OperationLogTemplateDto> GetAsync(string code)
        {
            var template = await _repository.FindAsync(code);

            return ObjectMapper.Map<OperationLogTemplate, OperationLogTemplateDto>(template);
        }

        public async Task<OperationLogTemplateDto> CreateAsync(OperationLogTemplateCreateDto input)
        {
            var match = await _repository.FindAsync(input.Code);

            if (match != null)
                throw new UserFriendlyException($"模板：{input.Code}已存在", FoundationErrorCodes.DuplicateKey);

            var template = new OperationLogTemplate(_guidGenerator.Create(), input.Code, input.Name, input.Comment);

            if (input.Items != null && input.Items.Count > 0)
            {
                foreach (var item in input.Items)
                {
                    var templateItem = new OperationLogTemplateItem(_guidGenerator.Create(), template.Id, item.FieldName, item.FieldCaption, item.FieldType);

                    template.AddItem(templateItem);
                }
            }

            template = await _repository.InsertAsync(template);

            var target = ObjectMapper.Map<OperationLogTemplate, OperationLogTemplateDto>(template);

            await _operationLogger.LogAsync(nameof(OperationLogTemplate), OperationType.Create, target, null);

            return target;
        }

        public async Task<OperationLogTemplateDto> UpdateAsync(OperationLogTemplateUpdateDto input)
        {
            var match = await _repository.FindAsync(input.Code);

            if (match != null && match.Id != input.Id)
                throw new UserFriendlyException($"模板：{input.Code}已存在", FoundationErrorCodes.DuplicateKey);

            var template = await _repository.GetAsync(input.Id);

            if (template == null)
                throw new UserFriendlyException($"模板：{input.Code}不存在", FoundationErrorCodes.NotExist);

            var source = ObjectMapper.Map<OperationLogTemplate, OperationLogTemplateDto>(template);

            template.Update(input.Code, input.Name, input.Comment);

            var items = new List<OperationLogTemplateItem>();

            foreach (var item in input.Items)
            {
                var id = item.Id == default ? _guidGenerator.Create() : item.Id;
                var templateItem = new OperationLogTemplateItem(id, match.Id, item.FieldName, item.FieldCaption, item.FieldType);

                items.Add(templateItem);
            }

            template.UpdateItems(items);

            template = await _repository.UpdateAsync(match);

            var target = ObjectMapper.Map<OperationLogTemplate, OperationLogTemplateDto>(template);

            await _operationLogger.LogAsync(nameof(OperationLogTemplate), OperationType.Update, source, target);

            return target;
        }

        public async Task DeleteAsync(Guid id)
        {
            var match = await _repository.GetAsync(id);

            if (match == null)
                throw new UserFriendlyException($"模板：{id}不存在", FoundationErrorCodes.NotExist);

            await _repository.DeleteAsync(id);

            var target = ObjectMapper.Map<OperationLogTemplate, OperationLogTemplateDto>(match);

            await _operationLogger.LogAsync(nameof(OperationLogTemplate), OperationType.Delete, target, null);
        }
    }
}
